package iohelper

import "fmt"

const (
	cByteDataMask     = 0b1111111  // 数据位掩码
	cByteHaveDataMask = 0b10000000 // 后面还有数据
)

type buffReader struct {
	buff []byte
	pos  int
}

var ErrEOF = fmt.Errorf("the buffer pos is end")

func (r *buffReader) RemainLen() int {
	return len(r.buff) - r.pos
}

func (r *buffReader) RemainBytes() []byte {
	return r.buff[r.pos:]
}

func (r *buffReader) SeekFromCurrent(n int) error {
	l := len(r.buff)
	if r.pos > l {
		return ErrEOF
	}

	r.pos += n
	if r.pos > l || r.pos < 0 {
		r.pos = l
	}
	return nil
}

func (r *buffReader) ResetPos() {
	r.pos = 0
}

func (r *buffReader) ReadByte() (v byte, err error) {
	if r.RemainLen() > 0 {
		v = r.buff[r.pos]
		r.pos++
	} else {
		return v, ErrEOF
	}
	return
}

func (r *buffReader) ReadUint16() (v uint16, err error) {
	if r.RemainLen() >= 2 {
		v = byteOrd.Uint16(r.buff[r.pos:])
		r.pos += 2
	} else {
		return v, ErrEOF
	}
	return
}

func (r *buffReader) ReadUint32() (v uint32, err error) {
	if r.RemainLen() >= 4 {
		v = byteOrd.Uint32(r.buff[r.pos:])
		r.pos += 4
	} else {
		return v, ErrEOF
	}
	return
}

func (r *buffReader) ReadUint64() (v uint64, err error) {
	if r.RemainLen() >= 8 {
		v = byteOrd.Uint64(r.buff[r.pos:])
		r.pos += 8
	} else {
		return v, ErrEOF
	}
	return
}

// 读取整数值
func (r *buffReader) ReadIntNum(numPtr any) (n int, err error) {
	var num uint64
	n, err = r.ReadDynInt(&num)
	switch v := numPtr.(type) {
	case *int8:
		*v = int8(num)
	case *uint8:
		*v = uint8(num)
	case *int16:
		*v = int16(num)
	case *uint16:
		*v = uint16(num)
	case *int32:
		*v = int32(num)
	case *uint32:
		*v = uint32(num)
	case *int64:
		*v = int64(num)
	case *uint64:
		*v = uint64(num)
	case *int:
		*v = int(num)
	default:
		return n, fmt.Errorf("不支持的类型 %v ", v)
	}
	return
}

// 返回:   数值      长度   错误
func (r *buffReader) ReadDynInt(v *uint64) (n int, err error) {
	*v = 0
	l := len(r.buff)
	for i := 0; i < 10; i++ {
		b := r.buff[r.pos]
		r.pos++
		*v |= uint64(b&cByteDataMask) << (i * 7)
		n++
		if b&cByteHaveDataMask == 0 {
			break // 读完了
		} else if r.pos >= l {
			err = fmt.Errorf("ReadDynInt: 数据未读完, 长度不够")
		}
	}
	return
}

func NewBuffReader(buff []byte) *buffReader {
	return &buffReader{buff: buff}
}
